home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 September / Macworld (1998-09).dmg / Shareware World / Info / For Developers / MacZoop 1.8.3 / Required Classes / Z Sources / ZWindowManager.cpp < prev   
Text File  |  1998-07-10  |  39KB  |  1,615 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"             
  5. *
  6. *
  7. *
  8. *            ZWindowManager.cpp        -- desktop class handles floaters
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZObjectArray.cpp"
  23.  
  24. #include    "MacZoop.h"
  25. #include    "ZWindow.h"
  26. #include    "ZDialog.h"
  27. #include    "ZEventHandler.h"
  28. #include    "ProjectSettings.h"
  29.  
  30. #if _USE_DIR_POPUP
  31. #include    "DirectoryPopup.h"
  32. #include    "FinderObjects.h"
  33. #endif
  34.  
  35. #if _WPOS_WINDOW_PLACEMENT
  36. #include    "ZResourceFile.h"
  37. #endif
  38.  
  39. #include    <dialogs.h>
  40.  
  41.  
  42. ZWindowManager*        gWindowManager = NULL;
  43. Rect                gZoomFXSourceRect = { 0, 0, 0, 0 };
  44.  
  45.  
  46. /*--------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  47.  
  48. ZWindowManager::ZWindowManager()
  49.     : ZComrade()
  50. {
  51.     // make the lists
  52.     
  53.     FailNIL( nonFloaters = new ZWindowList());
  54.     FailNIL( floaters = new ZWindowList());
  55.     
  56.     wmWindows = NULL;
  57.     wmMenu = NULL;
  58.     wmItemOffset = 0;
  59.     wmActive = TRUE;
  60.     
  61.     SetRect( &fStoredZoom, 0, 0, 0, 0 );
  62.     fStoredZoomSource = fStoredZoom;
  63.     
  64.     // set up member for controlling window placement
  65.     
  66.     globalPlaceLoc.h = 2;
  67.     globalPlaceLoc.v = GetMBarHeight() + 2;
  68.     
  69.     // we are the only one, and we are global
  70.     
  71.     gWindowManager = this;
  72. }
  73.  
  74. /*---------------------------------***  DESTRUCTOR  ***---------------------------------*/
  75.  
  76.  
  77. ZWindowManager::~ZWindowManager()
  78. {
  79.     if ( nonFloaters )
  80.         ForgetObject( nonFloaters );
  81.         
  82.     if ( floaters )
  83.         ForgetObject( floaters );
  84.         
  85.     if ( wmWindows )
  86.         ForgetObject( wmWindows );
  87. }
  88.  
  89.  
  90. /*---------------------------------***  ADDWINDOW  ***----------------------------------*/
  91. /*    
  92. add the window to the relevant list of windows, and set its initial (Z) position
  93. ----------------------------------------------------------------------------------------*/
  94.  
  95. void    ZWindowManager::AddWindow( ZWindow* aWindow )
  96. {
  97.     FailNILParam( aWindow );
  98.     
  99.     ZWindow*    zw = GetBottomFloater();
  100.     
  101.     // determine if this window is a floater or not:
  102.     
  103.     if ( aWindow->Floats())
  104.     {
  105.         BringBehind( aWindow, zw );
  106.         floaters->AppendItem( aWindow );
  107.     }
  108.     else
  109.     {
  110.         Boolean        eligibleWindow;
  111.         
  112.         eligibleWindow = ( ! IsDialog( aWindow )) ||
  113.                             ( IsDialog( aWindow ) && ! ((ZDialog*) aWindow )->IsModal());
  114.         
  115.         // move behind the bottom floater unless this is a modal dialog
  116.  
  117.         if ( eligibleWindow )
  118.             BringBehind( aWindow, zw );
  119.         
  120.         nonFloaters->AppendItem( aWindow );
  121.         
  122.         // if we're maintaining a "Windows" menu, append the window to our list if
  123.         // it non-floating and not a modal dialog box.
  124.         
  125.         if ( wmWindows && eligibleWindow )
  126.             wmWindows->AppendItem( aWindow );
  127.             
  128.         BuildWindowsMenu();
  129.     }    
  130.     
  131.     SendMessage( kWMMsgWindowAdded, aWindow );
  132. }
  133.  
  134.  
  135. /*--------------------------------***  REMOVEWINDOW  ***--------------------------------*/
  136. /*
  137. remove the window from the relevant list; make sure the next window is activated correctly.    
  138. ----------------------------------------------------------------------------------------*/
  139.  
  140. void    ZWindowManager::RemoveWindow( ZWindow* aWindow )
  141. {
  142.     FailNILParam( aWindow );
  143.     
  144.     aWindow->Hide();
  145.     
  146.     if ( aWindow->Floats())
  147.         floaters->DeleteObject( aWindow );
  148.     else
  149.     {
  150.         nonFloaters->DeleteObject( aWindow );
  151.         
  152.         if ( wmWindows )
  153.             wmWindows->DeleteObject( aWindow );
  154.         
  155.         // if all windows closed, reset global positioning variable
  156.         
  157.         if ( CountWindows() == 0 )
  158.         {
  159.             globalPlaceLoc.h = 2;
  160.             globalPlaceLoc.v = GetMBarHeight() + 2;
  161.         }
  162.     }
  163.     
  164.     SendMessage( kWMMsgWindowRemoved, aWindow );
  165. }
  166.  
  167.  
  168. /*-------------------------------***  INITIALLYPLACE  ***-------------------------------*/
  169. /*
  170. Call this after creating a window to place it initially. By default, this will stack the
  171. windows from top left towards bottom right, taking into account their correct title bar
  172. heights, etc. Override for other behaviours. Floating windows are ignored by this method.    
  173. ----------------------------------------------------------------------------------------*/
  174.  
  175. void    ZWindowManager::InitiallyPlace( ZWindow* aWindow )
  176. {
  177.     Rect    wBorder;
  178.     short    gh, gv;
  179.     
  180.     FailNILParam( aWindow );
  181.     
  182.     if ( ! aWindow->Floats())
  183.     {
  184.         aWindow->GetStructureFrameBorder( &wBorder );
  185.         
  186.         gh = globalPlaceLoc.h + wBorder.left;
  187.         gv = globalPlaceLoc.v + wBorder.top;
  188.         
  189.         aWindow->PlaceAt( gh, gv );
  190.         
  191.         globalPlaceLoc.h += wBorder.left + 2;
  192.         globalPlaceLoc.v += wBorder.top + 2;
  193.         
  194.         // if the bottom of the window falls off the screen, make it a bit less
  195.         // tall so that all its frame is visible.
  196.         
  197.         RgnHandle    wStruct;
  198.         short        overHang;
  199.         GDHandle    mainDev;
  200.         
  201.         mainDev = GetMainDevice();
  202.         aWindow->GetStructureRegion( wStruct = NewRgn());
  203.         
  204.         overHang = (*mainDev)->gdRect.bottom - (*wStruct)->rgnBBox.bottom;
  205.         
  206.         // if overhang is negative, we've gone too far, so make the window smaller.
  207.         
  208.         if ( overHang < 0 )
  209.         {
  210.             // only resize the window if it's a naturally resizable type, otherwise
  211.             // the user may end up with an unexpectedly nasty-looking window.
  212.             
  213.             WindowPtr    macWindow = aWindow->GetMacWindow();
  214.             short        wType;
  215.             
  216.             wType = GetWVariant( macWindow );
  217.  
  218.             if ( wType == documentProc  ||
  219.                  wType == zoomDocProc )
  220.             {
  221.                 wBorder = macWindow->portRect;
  222.             
  223.                 wBorder.bottom += overHang;
  224.                 aWindow->SetSize( wBorder.right - wBorder.left, wBorder.bottom - wBorder.top - 2, FALSE );
  225.             }
  226.             
  227.             // in any case the next window placed had better start back at the top...
  228.             
  229.             globalPlaceLoc.v = GetMBarHeight() + 2;
  230.             globalPlaceLoc.h += 10;
  231.         }
  232.         
  233.         DisposeRgn( wStruct );
  234.     }
  235. }
  236.  
  237.  
  238. /*---------------------------------***  HIDEWINDOW  ***---------------------------------*/
  239. /*    
  240. make the window invisible to the user. Does not change its front-to-back ordering unless
  241. it was the top one in its layer, in which case the one below it is selected.
  242. ----------------------------------------------------------------------------------------*/
  243.  
  244. void    ZWindowManager::HideWindow( ZWindow* aWindow )
  245. {
  246.     FailNILParam( aWindow );
  247.     
  248.     WindowPtr    w = aWindow->GetMacWindow();
  249.     
  250.     if ( w != NULL )
  251.     {
  252.         ShowHide( w, FALSE );
  253.         HiliteWindow( w, FALSE );
  254.         
  255.         SendMessage( kWMMsgWindowHidden, aWindow );
  256.     }
  257.     // if this was the top window, select the next none-hidden one
  258.     
  259.     if ( aWindow->Floats())
  260.     {
  261.         if ( aWindow == GetTopFloater() &&
  262.              floaters->CountItems() > 1 )
  263.         {
  264.             aWindow = floaters->GetObject( 2 );
  265.         
  266.             if ( aWindow && aWindow->IsVisible())
  267.                 SelectWindow( aWindow );
  268.         }
  269.     }
  270.     else
  271.     {
  272.         if ( aWindow == GetTopWindow())
  273.         {
  274.             // if it's a modal dialog that's being hidden, reactivate all floaters.
  275.             if ( IsDialog( aWindow ))
  276.                 Activate();
  277.  
  278.             if ( nonFloaters->CountItems() > 1 )
  279.             {
  280.                 aWindow = nonFloaters->GetObject( 2 );
  281.             
  282.                 if ( aWindow && aWindow->IsVisible())
  283.                     SelectWindow( aWindow );
  284.             }
  285.         }
  286.     }
  287. }
  288.  
  289.  
  290. /*---------------------------------***  SHOWWINDOW  ***---------------------------------*/
  291. /*    
  292. make the window visible to the user. Does not change its front-to-back ordering
  293. ----------------------------------------------------------------------------------------*/
  294.  
  295. void    ZWindowManager::ShowWindow( ZWindow* aWindow )
  296. {
  297.     FailNILParam( aWindow );
  298.     
  299.     if ( ! aWindow->IsVisible())
  300.     {
  301.         #if _ZOOM_RECT_FX
  302.         
  303.         if ( gMacInfo.hasDragManager )
  304.         {
  305.             RgnHandle    wStruct;
  306.         
  307.             aWindow->GetStructureRegion( wStruct = NewRgn());
  308.             aWindow->zoomSource = gZoomFXSourceRect;
  309.             
  310.             ZoomRects( &gZoomFXSourceRect, &(*wStruct)->rgnBBox, 10, kZoomAccelerate );
  311.             DisposeRgn( wStruct );
  312.         }
  313.         #endif
  314.         
  315.         ShowHide( aWindow->GetMacWindow(), TRUE );
  316.         SendMessage( kWMMsgWindowShown, aWindow );
  317.     
  318.         if ( aWindow == GetTopWindow() ||
  319.              aWindow == GetTopFloater())
  320.             SelectWindow( aWindow );
  321.     }
  322. }
  323.  
  324.  
  325. /*--------------------------------***  SELECTWINDOW  ***--------------------------------*/
  326. /*    
  327. make the window active. This handles the front-to-back ordering and creates the "floating"
  328. window illusion.
  329. ----------------------------------------------------------------------------------------*/
  330.  
  331. void    ZWindowManager::SelectWindow( ZWindow* aWindow )
  332. {
  333.     FailNILParam( aWindow );
  334.     
  335.     // this is where a certain amount of cunning comes in. To "Select" a non-floater, it
  336.     // is actually moved to come behind the bottom floater. Floaters are treated normally.
  337.     // Dialogs can come in front of all windows, though they will be set to non-floating.
  338.     
  339.     ZWindow*    zw;
  340.     long        i;
  341.     
  342.     if (! aWindow->IsVisible())
  343.     {
  344.         // if window hitherto has not been seen by the user, and the setting indicates we
  345.         // want the effect, perform the zoom open animation
  346.         
  347.         #if _ZOOM_RECT_FX
  348.         
  349.         if ( gMacInfo.hasDragManager )
  350.         {
  351.             RgnHandle    wStruct;
  352.         
  353.             aWindow->GetStructureRegion( wStruct = NewRgn());
  354.             aWindow->zoomSource = gZoomFXSourceRect;
  355.             
  356.             ZoomRects( &gZoomFXSourceRect, &(*wStruct)->rgnBBox, 10, kZoomAccelerate );
  357.             DisposeRgn( wStruct );
  358.         }
  359.         #endif
  360.     }    
  361.     // manipulate our lists and the mac window list
  362.     
  363.     if ( aWindow->Floats())
  364.     {
  365.         i = floaters->FindIndex( aWindow );
  366.         
  367.         // move to head of list, if not there already
  368.         
  369.         if ( i > 0 )
  370.         {
  371.             // deactivate current "top"
  372.             
  373.             zw = GetTopFloater();
  374.             
  375.             if ( zw )
  376.             {
  377.                 #if _ALL_FLOATERS_ACTIVE == OFF
  378.                 HiliteWindow( zw->GetMacWindow(), FALSE );
  379.                 #endif
  380.                 
  381.                 zw->Deactivate();
  382.                 SendMessage( kWMMsgFloaterDeactivated, zw );
  383.             }
  384.             
  385.             floaters->MoveToFront( i );
  386.             BringBehind( aWindow, NULL );
  387.         }    
  388.         // hilite and activate the new "top" window
  389.         // if window is not visible, make it so
  390.     
  391.         ShowHide( aWindow->GetMacWindow(), TRUE );
  392.         aWindow->Activate();
  393.         HiliteWindow( aWindow->GetMacWindow(), TRUE );
  394.         SendMessage( kWMMsgFloaterActivated, aWindow );
  395.     }
  396.     else
  397.     {
  398.         i = nonFloaters->FindIndex( aWindow );
  399.         
  400.         // if already on top, do nothing
  401.         
  402.         if ( i > 1 )
  403.         {
  404.             // deactivate the current "top"
  405.             
  406.             zw = GetTopWindow();
  407.             
  408.             if ( zw )
  409.                 PostActivation( zw, FALSE );
  410.             
  411.             // move to head of list
  412.             
  413.             nonFloaters->MoveToFront( i );
  414.         }    
  415.         // bring window behind the bottom floater, unless it's a dialog, in which
  416.         // case it's put on top of everything
  417.  
  418.         if ( IsDialog( aWindow ))
  419.         {
  420.             Deactivate();
  421.             BringBehind( aWindow, NULL );
  422.         }
  423.         else
  424.         {
  425.             zw = GetBottomFloater();
  426.             BringBehind( aWindow, zw );
  427.         }
  428.         
  429.         // hilite and activate the new "top" window
  430.         // if window is not visible, make it so
  431.     
  432.         ShowHide( aWindow->GetMacWindow(), TRUE );
  433.         PostActivation( aWindow, TRUE );
  434.     }
  435. }
  436.  
  437.  
  438. /*-----------------------------***  DRAGWINDOWOUTLINE  ***------------------------------*/
  439. /*    
  440. drag the outline of the window and move it when the mouse is released. This replaces the
  441. toolbox routine DragWindow, and in addition does a nicer job of clipping the outline.
  442. ----------------------------------------------------------------------------------------*/
  443.  
  444. void    ZWindowManager::DragWindowOutline( ZWindow* aWindow, Point startPt, const short modifiers )
  445. {
  446.     FailNILParam( aWindow );
  447.     
  448.     // replaces the toolbox DragWindow, because that will bring a window to the front if
  449.     // you let it.
  450.     
  451.     WindowPtr    w;
  452.     RgnHandle    dragRgn, temp = NULL;
  453.     Rect        limitRect;
  454.     long        dragOffset;
  455.     GrafPort    screenPort;
  456.     GrafPtr        savePort;
  457.     Point        wPosition;
  458.     
  459.     w = aWindow->GetMacWindow();
  460.     PauseCursorAnimation( 0 );
  461.     
  462.     // if window frontmost and command key down, call command-click hook and return. The hook
  463.     // can be overridden to implement stuff such as popping up a directory path menu, etc.
  464.     
  465.     if ( aWindow == GetTopWindow() &&
  466.          ( modifiers & cmdKey ) == cmdKey )
  467.     {
  468.         // the hook returns a boolean to indicate whether processing should continue or not.
  469.         // If FALSE, we continue, otherwise we abort. The default hook method just returns FALSE
  470.         
  471.         if ( CommandClickInFrontDragBar( aWindow, startPt ))
  472.             return;
  473.     }
  474.     
  475.     // select the window if command key not down
  476.     
  477.     #if _DRAGWINDOW_COMPATIBLE == OFF
  478.     
  479.     if (( modifiers & cmdKey ) == 0 &&
  480.         aWindow != GetTopWindow() &&
  481.         aWindow != GetTopFloater())
  482.     {
  483.         SelectWindow( aWindow );
  484.     }
  485.     #if _UPDATE_ON_SELECT
  486.     
  487.     aWindow->PerformUpdate();
  488.     
  489.     #endif
  490.     
  491.     #endif
  492.     
  493.     // get the limit rect
  494.     
  495.     limitRect = (*GetGrayRgn())->rgnBBox;
  496.     InsetRect( &limitRect, 4, 4 );
  497.     
  498.     // get the outline to drag. This is simply a copy of the window's structure region
  499.     
  500.     FailNIL( dragRgn = NewRgn());
  501.     
  502.     CopyRgn(((WindowPeek) w)->strucRgn, dragRgn );
  503.     
  504.     // set up a port in which to drag the outline. We do this to be good citizens,
  505.     // since meddling with the Mac's Window Manager port is tricky to get away with.
  506.     
  507.     GetPort( &savePort );
  508.     OpenPort( &screenPort );
  509.     SetPort( &screenPort );
  510.     
  511.     // make sure we can drag on the whole desktop
  512.     
  513.     screenPort.portRect = (*GetGrayRgn())->rgnBBox;
  514.     SetClip( GetGrayRgn());
  515.     CopyRgn( screenPort.clipRgn, screenPort.visRgn );
  516.     
  517.     // Remove the regions of all windows in front from the clip region, so it is clearer
  518.     // what will happen when the window moves.
  519.     
  520.     FailNIL( temp = NewRgn());
  521.     CalcWindowRgns( aWindow, temp );
  522.     DiffRgn( screenPort.clipRgn, temp, screenPort.clipRgn );
  523.     
  524.     // if we have system 8.0 or later, use a 2-pixel gray drag region, not a 1-pixel
  525.     
  526.     if ( gMacInfo.systemVersion >= 0x0800 )
  527.     {
  528.         CopyRgn( dragRgn, gUtilRgn );
  529.         InsetRgn( gUtilRgn, 2, 2 );
  530.         DiffRgn( dragRgn, gUtilRgn, dragRgn );
  531.     }
  532.     
  533.     // the mouse may have moved away from the startPt already, since the update may have taken
  534.     // a while. In order to prevent the window jumping in this situation, we just check that the
  535.     // mouse is still in fact, down!
  536.     
  537.     if ( StillDown())
  538.         dragOffset = DragGrayRgn( dragRgn, startPt, &limitRect, &limitRect, noConstraint, NULL );
  539.     else
  540.         dragOffset = kMouseUpOutOfSlop;
  541.         
  542.     // delete our port
  543.     
  544.     ClosePort( &screenPort );
  545.     SetPort( savePort );
  546.     
  547.     // check the window drag wasn't bogus:
  548.     
  549.     if ( dragOffset != kMouseUpOutOfSlop )
  550.     {
  551.         // OK, figure out where the window moved to, and move it there. If the command key
  552.         // is not down, select tha' booga!
  553.         
  554.         SetPort( w );
  555.         
  556.         wPosition = topLeft( w->portRect );
  557.         LocalToGlobal( &wPosition );
  558.         SetPort( savePort );
  559.         
  560.         // if we are exactly compatible with toolbox DragWindow(), then select the window here
  561.         
  562.         #if _DRAGWINDOW_COMPATIBLE
  563.         
  564.         if (( modifiers & cmdKey ) == 0 &&
  565.             aWindow != GetTopWindow() &&
  566.             aWindow != GetTopFloater())
  567.             SelectWindow( aWindow );
  568.         
  569.         #endif
  570.         
  571.         MoveWindow( w, wPosition.h + LoWord( dragOffset ), wPosition.v + HiWord( dragOffset ), FALSE );
  572.         SendMessage( kWMMsgWindowMoved, aWindow );
  573.     }    
  574.     // clean up
  575.     
  576.     DisposeRgn( dragRgn );
  577.     
  578.     if ( temp )    
  579.         DisposeRgn( temp );
  580.         
  581.     ResumeCursorAnimation();
  582. }
  583.  
  584.  
  585. /*-----------------------------------***  SUSPEND  ***----------------------------------*/
  586. /*    
  587. application is suspending- hide the floaters
  588. ----------------------------------------------------------------------------------------*/
  589.  
  590. void    ZWindowManager::Suspend()
  591. {
  592.     // the application is being suspended, so all floaters should be hidden
  593.     
  594.     ZWindow        *aFloater, *tw;
  595.     short        i;
  596.     
  597.     for (i = 1; i <= floaters->CountItems(); i++)
  598.     {
  599.         aFloater = floaters->GetObject( i );
  600.         
  601.         if ( aFloater )
  602.             ShowHideFloater( aFloater, TRUE );
  603.     }
  604.     
  605.     tw = GetTopWindow();
  606.     
  607.     if ( tw )
  608.         PostActivation( tw, FALSE );
  609. }
  610.  
  611. /*-----------------------------------***  RESUME  ***-----------------------------------*/
  612. /*    
  613. application is resuming- show the floaters
  614. ----------------------------------------------------------------------------------------*/
  615.  
  616. void    ZWindowManager::Resume()
  617. {
  618.     // the application is being resumed, so all floaters should be re-shown.
  619.     
  620.     ZWindow        *aFloater, *tw;
  621.     short        i;
  622.     
  623.     for (i = 1; i <= floaters->CountItems(); i++)
  624.     {
  625.         aFloater = floaters->GetObject( i );
  626.         
  627.         if ( aFloater )
  628.             ShowHideFloater( aFloater, FALSE );
  629.     }
  630.  
  631.     tw = GetTopWindow();
  632.     
  633.     if ( tw )
  634.         PostActivation( tw, TRUE );
  635. }
  636.  
  637. /*---------------------------------***  DEACTIVATE  ***---------------------------------*/
  638. /*    
  639. a modal dialog is coming up, so deactivate all floaters and the top window. You need to
  640. call this whenever you put up a non ZDialog-based dialog, such as standard file, for
  641. consistent behaviour with MacZoop dialogs. Those objects will call this automatically.
  642. ----------------------------------------------------------------------------------------*/
  643.  
  644. void    ZWindowManager::Deactivate()
  645. {
  646.     // a dialog is up, so all floaters plus the top window must be deactivated
  647.     
  648.     if ( ! wmActive )
  649.         return;
  650.         
  651.     wmActive = FALSE;
  652.     ZWindow*    zw;
  653.     
  654. #if _ALL_FLOATERS_ACTIVE == OFF
  655.     
  656.     zw = GetTopFloater();
  657.     
  658.     if ( zw )
  659.         PostActivation( zw, FALSE );
  660.         
  661. #else
  662.     
  663.     short    i;
  664.     
  665.     for (i = 1; i <= floaters->CountItems(); i++ )
  666.     {
  667.         zw = floaters->GetObject( i );
  668.     
  669.         if ( zw )
  670.             PostActivation( zw, FALSE );
  671.     }
  672.     
  673. #endif
  674.  
  675.     zw = GetTopWindow();
  676.     
  677.     if ( zw )
  678.         PostActivation( zw, FALSE );
  679.     
  680. }
  681.  
  682.  
  683. /*----------------------------***  DEACTIVATEFORDIALOG  ***-----------------------------*/
  684. /*    
  685. in order to support nice zoom rects when non-MacZoop dialogs are displayed, this method
  686. can be called instead of Deactivate to provide the animation by proxy for the dialog. If
  687. the FX are turned off, this is exactly equivalent to Deactivate. This should ONLY be called
  688. for dialogs and alerts that are not ZDialog objects.
  689. ----------------------------------------------------------------------------------------*/
  690.  
  691. void    ZWindowManager::DeactivateForDialog( short dlogID, Boolean isAlert  )
  692. {
  693.     Deactivate();
  694.     SendMessage( kWMMsgMacDialogUp, NULL );
  695.     
  696.     #if _ZOOM_RECT_FX
  697.     
  698.     // in order to display the animation by proxy for the dialog we are about to put
  699.     // up, we need to obtain the dialog's window frame by taking a peek into the
  700.     // dialog record
  701.     
  702.     if ( gMacInfo.hasDragManager )
  703.     {
  704.         Rect            r;
  705.         AlertTHndl        atH;
  706.         DialogTHndl        dtH;
  707.         
  708.         if ( isAlert )
  709.         {
  710.             atH = (AlertTHndl) GetResource( 'ALRT', dlogID );
  711.         
  712.             if ( atH )
  713.             {
  714.                 r = (*atH)->boundsRect;
  715.                 ReleaseResource((Handle) atH );
  716.             }
  717.         }
  718.         else
  719.         {    
  720.             dtH = (DialogTHndl) GetResource( 'DLOG', dlogID );
  721.             
  722.             if ( dtH )
  723.             {
  724.                 r = (*dtH)->boundsRect;
  725.                 ReleaseResource((Handle) dtH );
  726.             }    
  727.         }
  728.         
  729.         // we are going to need to assume that the dialog/alert is going to be placed on the screen
  730.         // in the standard alert position (for now- there are ways to be more intelligent about this)
  731.         // so we have to compute that location:
  732.         
  733.         Rect    screen = qd.screenBits.bounds;
  734.         
  735.         screen.top += GetMBarHeight();
  736.         
  737.         short    topSpace = screen.bottom - screen.top - r.bottom - r.top;
  738.         short    leftSpace = screen.right - screen.left - r.right - r.left;
  739.         
  740.         OffsetRect( &r, ( leftSpace / 2 ) - r.left, ( topSpace / 4 ) - r.top );
  741.         
  742.         // that's the one- do the animation
  743.             
  744.         ZoomRects( &gZoomFXSourceRect, &r, 10, kZoomAccelerate );
  745.         
  746.         // store the rects on behalf of the dialog/alert so we can do the reverse animation
  747.         // when we are reactivated
  748.         
  749.         fStoredZoomSource = gZoomFXSourceRect;
  750.         fStoredZoom = r;
  751.     }
  752.  
  753.     #endif
  754. }
  755.  
  756.  
  757. /*----------------------------------***  ACTIVATE  ***----------------------------------*/
  758. /*    
  759. the modal dialog is going away, so reactivate the floaters and top window
  760. ----------------------------------------------------------------------------------------*/
  761.  
  762. void    ZWindowManager::Activate()
  763. {
  764.     // a dialog is going away, so all floaters plus the top window must be reactivated
  765.     
  766.     if ( wmActive )
  767.         return;
  768.  
  769.     wmActive = TRUE;
  770.     
  771.     SendMessage( kWMMsgMacDialogDown, NULL );
  772.     
  773.     ZWindow*    zw;
  774.     
  775. #if _ALL_FLOATERS_ACTIVE == OFF
  776.     
  777.     zw = GetTopFloater();
  778.     
  779.     if ( zw )
  780.         PostActivation( zw, TRUE );
  781.  
  782. #else
  783.     
  784.     short    i;
  785.     
  786.     for (i = 1; i <= floaters->CountItems(); i++ )
  787.     {
  788.         zw = floaters->GetObject( i );
  789.     
  790.         if ( zw )
  791.             PostActivation( zw, TRUE );
  792.     }
  793.     
  794. #endif
  795.  
  796.     // if we have a stored zoom, zoom down from it.
  797.     
  798. #if _ZOOM_RECT_FX
  799.     
  800.     if ( ! EmptyRect( &fStoredZoom ) && gMacInfo.hasDragManager )
  801.     {
  802.         ZoomRects( &fStoredZoom, &fStoredZoomSource, 10, kZoomDecelerate );
  803.     
  804.         SetRect( &fStoredZoom, 0, 0, 0, 0 );
  805.         fStoredZoomSource = fStoredZoom;
  806.     }
  807.     
  808. #endif
  809.  
  810.     zw = GetTopWindow();
  811.     
  812.     if ( zw )
  813.         PostActivation( zw, TRUE );
  814. }
  815.  
  816.  
  817. /*--------------------------------***  GETTOPWINDOW  ***--------------------------------*/
  818. /*    
  819. get uppermost non-floating window
  820. ----------------------------------------------------------------------------------------*/
  821.  
  822. ZWindow*    ZWindowManager::GetTopWindow()
  823. {
  824.     // returns the top non-floating window
  825.     
  826.     if ( nonFloaters->CountItems() > 0 )
  827.         return nonFloaters->GetObject( 1 );
  828.     else
  829.         return NULL;
  830. }
  831.  
  832.  
  833. /*-------------------------------***  GETTOPFLOATER  ***--------------------------------*/
  834. /*    
  835. get uppermost floating window
  836. ----------------------------------------------------------------------------------------*/
  837.  
  838. ZWindow*    ZWindowManager::GetTopFloater()
  839. {
  840.     // returns the top floating window (even if not visible)
  841.     
  842.     if ( floaters->CountItems() > 0 )
  843.         return floaters->GetObject( 1 );
  844.     else
  845.         return NULL;
  846. }
  847.  
  848.  
  849. /*------------------------------***  GETBOTTOMFLOATER  ***------------------------------*/
  850. /*    
  851. get the last window in the floating layer. Top window is the one behind this.
  852. ----------------------------------------------------------------------------------------*/
  853.  
  854. ZWindow*    ZWindowManager::GetBottomFloater()
  855. {
  856.     // returns the bottom-most VISIBLE floater
  857.     
  858.     long    fCount = floaters->CountItems();
  859.     
  860.     if ( fCount > 0 )
  861.     {
  862.         ZWindow*    botFloater;
  863.         
  864.         // iterate through the list of floaters looking for the bottom-most visible one.
  865.         // Iterate in reverse order to facilitate finding the bottom one.
  866.         
  867.         while( fCount )
  868.         {
  869.             botFloater = floaters->GetObject( fCount-- );
  870.             
  871.             if ( botFloater->IsVisible())
  872.                 break;
  873.             else
  874.                 botFloater = NULL;
  875.         }
  876.         
  877.         return botFloater;    
  878.     }
  879.     else
  880.         return NULL;    
  881. }
  882.  
  883.  
  884. /*------------------------------***  CHECKDIALOGEVENT  ***------------------------------*/
  885. /*    
  886. determine if the event is aimed at a dialog. This replaces the toolbox IsDialogEvent call
  887. such that it does not call FrontWindow().
  888. ----------------------------------------------------------------------------------------*/
  889.  
  890. Boolean        ZWindowManager::CheckDialogEvent( EventRecord* theEvent )
  891. {
  892.     // the event is for a dialog if the window kind explicitly passed with certain events is
  893.     // a dialog, or for other events, that the top window as we know it is a dialog.
  894.     
  895.     WindowPeek    w;
  896.     Boolean        result = FALSE;
  897.     ZWindow*    zw;
  898.     
  899.     // is this a window explicit event?
  900.     
  901.     if ( theEvent->what == updateEvt ||
  902.          theEvent->what == activateEvt )
  903.     {
  904.         // yes, so get the window and see if it's a dialog
  905.         
  906.         w = (WindowPeek) theEvent->message;
  907.     
  908.         result = ( w->windowKind == dialogKind );
  909.     }
  910.     else
  911.     {
  912.         // is the event a mouse down? If so we need to see if it was in the active dialog
  913.         // window.
  914.         
  915.         if ( theEvent->what == mouseDown )
  916.         {
  917.             short    part = FindWindow( theEvent->where, (WindowPtr*) &w );
  918.             
  919.             zw = GetTopWindow();
  920.             
  921.             result = (    part == inContent &&
  922.                         w->windowKind == dialogKind &&
  923.                         zw &&
  924.                         zw->GetMacWindow() == (WindowPtr) w );
  925.         }
  926.         else
  927.         {
  928.             zw = GetTopWindow();
  929.             
  930.             // we do our own checks but also call the toolbox IsDialogEvent, so that
  931.             // ballon help in dialogs is correctly displayed. (Balloon help hooks into
  932.             // this routine to provide dialog balloons).
  933.             
  934.             result = ( zw &&
  935.                        ((WindowPeek) zw->GetMacWindow())->windowKind == dialogKind &&
  936.                        ( theEvent->what == keyDown ||
  937.                          theEvent->what == autoKey ||
  938.                          IsDialogEvent( theEvent )));
  939.         }
  940.     }
  941.     return result;    
  942. }
  943.  
  944.  
  945. /*--------------------------------***  LOCATEWINDOW  ***--------------------------------*/
  946. /*    
  947. find the window under the mouse, or NULL if none are
  948. ----------------------------------------------------------------------------------------*/
  949.  
  950. ZWindow*    ZWindowManager::LocateWindow( const Point globalMouse )
  951. {
  952.     WindowPeek    w;
  953.     ZWindow*    zw = NULL;
  954.     
  955.     w = ( WindowPeek ) FrontWindow();
  956.     
  957.     while ( w )
  958.     {
  959.         if ( PtInRgn( globalMouse, w->strucRgn ))
  960.         {        
  961.             zw = GetZWindow(( WindowPtr ) w );
  962.             break;
  963.         }
  964.         
  965.         w = w->nextWindow;
  966.     }
  967.     
  968.     return zw;
  969. }
  970.  
  971.  
  972. /*--------------------------------***  GETNTHWINDOW  ***--------------------------------*/
  973. /*    
  974. return the window <n>, or NULL if bad index
  975. ----------------------------------------------------------------------------------------*/
  976.  
  977. ZWindow*    ZWindowManager::GetNthWindow( const long n )
  978. {
  979.     ZWindow*    zw = NULL;
  980.     
  981.     try
  982.     {
  983.         zw = nonFloaters->GetObject( n );
  984.     }
  985.     catch( OSErr err )
  986.     {
  987.     }
  988.     
  989.     return zw;
  990. }
  991.  
  992.  
  993. /*--------------------------------***  GETNTHFLOATER  ***-------------------------------*/
  994. /*    
  995. return the floating window <n>, or NULL if bad index
  996. ----------------------------------------------------------------------------------------*/
  997.  
  998. ZWindow*    ZWindowManager::GetNthFloater( const long n )
  999. {
  1000.     ZWindow*    zw = NULL;
  1001.     
  1002.     try
  1003.     {
  1004.         zw = floaters->GetObject( n );
  1005.     }
  1006.     catch( OSErr err )
  1007.     {
  1008.     }
  1009.     
  1010.     return zw;
  1011. }
  1012.     
  1013.  
  1014. /*----------------------------------***  ISDIALOG  ***----------------------------------*/
  1015. /*    
  1016. is the window a modal dialog?
  1017. ----------------------------------------------------------------------------------------*/
  1018.  
  1019. Boolean        ZWindowManager::IsDialog( ZWindow* aWindow )
  1020. {
  1021.     // return TRUE if the window is a modal dialog (but not for modeless ones)
  1022.     
  1023.     if ( aWindow )
  1024.     {
  1025.         ZDialog*    zd = dynamic_cast<ZDialog*> ( aWindow );
  1026.         
  1027.         if (zd && zd->IsModal())
  1028.             return TRUE;
  1029.         else
  1030.             return FALSE;
  1031.     }
  1032.     else
  1033.         return FALSE;
  1034. }
  1035.  
  1036.  
  1037. /*--------------------------***  GETUNIQUEUNTITLEDNAME  ***-----------------------------*/
  1038. /*    
  1039. as part of the human interface guidelines adherence, we automatically name new windows
  1040. untitled, untitled 1, etc. This method scans through the names of all the windows in the
  1041. main list (ignores floaters), making sure the name is unique. If not, it appends 1, 2, etc
  1042. until the name is unique. If the name was unique, it returns FALSE, otherwise TRUE. i.e.
  1043. TRUE means we modified the name. Uses EqualString to compare names, ignores case.
  1044. ----------------------------------------------------------------------------------------*/
  1045.  
  1046. Boolean        ZWindowManager::GetUniqueUntitledName( Str255 wName )
  1047. {
  1048.     short        n = 1, i;
  1049.     Boolean        result = FALSE, match;
  1050.     Str255        sName, temp;
  1051.     ZWindow*    zw;
  1052.     
  1053.     CopyPString( wName, temp );
  1054.     
  1055.     do
  1056.     {
  1057.         match = FALSE;
  1058.         
  1059.         for ( i = 1; i <= nonFloaters->CountItems(); i++ )
  1060.         {    
  1061.             zw = nonFloaters->GetObject( i );
  1062.             zw->GetName( sName );
  1063.             
  1064.             if ( EqualString( temp, sName, FALSE, FALSE ))
  1065.             {
  1066.                 match = TRUE;
  1067.                 break;
  1068.             }
  1069.         }
  1070.         
  1071.         if ( match )
  1072.         {
  1073.             // the name matched some window, so append a digit and try again
  1074.         
  1075.             CopyPString( wName, temp );
  1076.             
  1077.             NumToString( n++, sName );
  1078.             ConcatPStrings( temp, "\p " );
  1079.             ConcatPStrings( temp, sName );
  1080.         }
  1081.         else
  1082.         {
  1083.             result = TRUE;
  1084.             CopyPString( temp, wName );
  1085.         }
  1086.     }
  1087.     while( ! result );
  1088.     
  1089.     return result;    
  1090. }
  1091.  
  1092.  
  1093. /*----------------------------------***  FLOATIDLE  ***---------------------------------*/
  1094. /*    
  1095. pass idle to each floater, in case they do periodic action
  1096. ----------------------------------------------------------------------------------------*/
  1097.  
  1098. void    ZWindowManager::FloatIdle()
  1099. {
  1100.     long        i;
  1101.     ZWindow*    aFloater;
  1102.     
  1103.     for( i = 1; i <= floaters->CountItems(); i++ )
  1104.     {
  1105.         aFloater = floaters->GetObject( i );
  1106.     
  1107.         if ( aFloater )
  1108.             aFloater->Idle();
  1109.     }    
  1110. }
  1111.  
  1112.  
  1113. /*---------------------------------***  COUNTWINDOWS  ***-------------------------------*/
  1114. /*    
  1115. return the number of non-floating windows the manager knows about
  1116. ----------------------------------------------------------------------------------------*/
  1117.  
  1118. short        ZWindowManager::CountWindows()
  1119. {
  1120.     return nonFloaters->CountItems();
  1121. }
  1122.  
  1123. /*---------------------------------***  COUNTFLOATERS  ***------------------------------*/
  1124. /*    
  1125. return the number of floating windows the manager knows about
  1126. ----------------------------------------------------------------------------------------*/
  1127.  
  1128. short        ZWindowManager::CountFloaters()
  1129. {
  1130.     return floaters->CountItems();
  1131. }
  1132.  
  1133.  
  1134. /*--------------------------------***  SETWINDOWSMENU  ***------------------------------*/
  1135. /*    
  1136. sets the passed menu to be the application's "Windows" menu. Called by ZMenuBar- do not
  1137. call this method directly- use gMenuBar->NominateWindowsMenu() instead. This should be
  1138. called before any non-floating windows are created.
  1139. ----------------------------------------------------------------------------------------*/
  1140.  
  1141. void        ZWindowManager::SetWindowsMenu( MenuHandle aMenu )
  1142. {
  1143.     FailNILParam( aMenu );
  1144.     
  1145.     wmMenu = aMenu;
  1146.     wmItemOffset = CountMenuItems( aMenu );
  1147.     
  1148.     // make a list to keep an ordered list of windows that does not depend on
  1149.     // the front-to-back order
  1150.     
  1151.     FailNIL( wmWindows = new ZWindowList());
  1152.     
  1153.     BuildWindowsMenu();
  1154. }
  1155.  
  1156.  
  1157. /*-----------------------------***  SELECTWINDOWFROMMENU  ***---------------------------*/
  1158. /*    
  1159. called only by the main menubar to select the window from the menu. Do not call this
  1160. yourself.
  1161. ----------------------------------------------------------------------------------------*/
  1162.  
  1163. void        ZWindowManager::SelectWindowFromMenu( const short itemID )
  1164. {
  1165.     if ( wmMenu && wmWindows && !IsDialog( GetTopWindow()))
  1166.     {
  1167.         short    n = itemID - wmItemOffset;
  1168.         
  1169.         if ( wmItemOffset > 0 )
  1170.             n--;    // allow for divider line
  1171.         
  1172.         if (( n > 0 ) && ( n <= wmWindows->CountItems()))
  1173.         {
  1174.             ZWindow*    zw = wmWindows->GetObject( n );
  1175.         
  1176.             if ( zw )
  1177.                 zw->Select();
  1178.         }
  1179.     }
  1180. }
  1181.  
  1182.  
  1183. /*-------------------------------***  ZOOMWINDOWCLOSED  ***-----------------------------*/
  1184. /*
  1185. called when a window is closed to perform the "zoom closed" animation, if this effect
  1186. is enabled.    
  1187. ----------------------------------------------------------------------------------------*/
  1188.  
  1189. void        ZWindowManager::ZoomWindowClosed( ZWindow* aWindow )
  1190. {
  1191. #if _ZOOM_RECT_FX
  1192.  
  1193.     if ( gMacInfo.hasDragManager && ( gApplication->GetPhase() == kRunning ))
  1194.     {
  1195.         RgnHandle    wStruct;
  1196.         
  1197.         aWindow->GetStructureRegion( wStruct = NewRgn());
  1198.         
  1199.         ZoomRects( &(*wStruct)->rgnBBox, &aWindow->zoomSource, 10, kZoomDecelerate );
  1200.         DisposeRgn( wStruct );
  1201.     }
  1202.  
  1203. #endif
  1204. }
  1205.  
  1206.  
  1207. Boolean        ZWindowManager::CommandClickInFrontDragBar( ZWindow* target, const Point startPt )
  1208. {
  1209. #if _USE_DIR_POPUP
  1210.     
  1211.     // if we're using the directory pop-up code, call that here.
  1212.     // has the window got a file?
  1213.     
  1214.     FSSpec        ffs;
  1215.     Boolean        result;    
  1216.     
  1217.     target->GetFileSpec( &ffs );
  1218.     
  1219.     if ( ffs.vRefNum != kNoFile )
  1220.     {
  1221.         // we have a spec, so do that menu tracking thang, courtesy of Marco Piovanelli...
  1222.         
  1223.         result = TrackDirectoryPopup( &ffs, target->GetMacWindow(), startPt );
  1224.         
  1225.         if ( result )
  1226.         {
  1227.             // ffs now contains spec of selected directory, so we now assemble
  1228.             // an apple event to tell the Finder to open it.
  1229.             
  1230.             FailOSErr( OpenFinderObject( &ffs ));
  1231.         }
  1232.         else
  1233.             result = ! StillDown();
  1234.             
  1235.         return result;
  1236.     }
  1237.     else
  1238.         return FALSE;
  1239.  
  1240. #else
  1241.     return FALSE;
  1242. #endif
  1243. }
  1244.  
  1245.  
  1246. short        ZWindowManager::SaveWindowPosition( ZWindow* aWindow, ZResourceFile* aFile, short id )
  1247. {
  1248. #if _WPOS_WINDOW_PLACEMENT
  1249.  
  1250.     WPosHdl                wpH;
  1251.     ZResourceFile*        st;
  1252.     Rect                pr;
  1253.     short                x, y;
  1254.     
  1255.     FailNILParam( aWindow );
  1256.     
  1257.     // if <aFile> is NULL, use gPrefsFile if it exists. Otherwise do nothing.
  1258.     
  1259.     if ( aFile == NULL )
  1260.         st = (ZResourceFile*) gPrefsFile;
  1261.     else
  1262.         st = aFile;
  1263.         
  1264.     if ( st == NULL )
  1265.         return 0;
  1266.     
  1267.     FailNIL( wpH = ( WPosHdl ) NewHandleClear( sizeof( WPosResource )));
  1268.     
  1269.     aWindow->GetGlobalPosition( &x, &y );
  1270.     pr = aWindow->GetMacWindow()->portRect;
  1271.     
  1272.     (*wpH)->globalH = x;
  1273.     (*wpH)->globalV = y;
  1274.     (*wpH)->width = pr.right - pr.left;
  1275.     (*wpH)->height = pr.bottom - pr.top;
  1276.     
  1277.     if ( id == 0 )
  1278.         id = _UNIQUE_ID;
  1279.         
  1280.     // make sure the resource fork is open, etc. In general the file should already exist-
  1281.     // this will create it if not, but you'll have more control if you deal with this.
  1282.     
  1283.     if ( ! st->IsReal() || ! st->HasResFork())
  1284.         st->CreateResFork();
  1285.         
  1286.     short    rf = st->GetResourceRefNumber();
  1287.     
  1288.     try
  1289.     {    
  1290.         st->OpenResFork();
  1291.         st->WriteResource((Handle) wpH, kWindowPosResType, id );
  1292.         
  1293.         ReleaseResource((Handle) wpH );
  1294.         
  1295.         if ( rf == _NOT_OPEN )
  1296.             st->CloseResFork();
  1297.     }
  1298.     catch( OSErr err )
  1299.     {
  1300.         if ( rf == _NOT_OPEN )
  1301.             st->CloseResFork();
  1302.             
  1303.         // don't propagate- not important.
  1304.     }
  1305.     
  1306. #endif
  1307.  
  1308.     // return the ID we actually used: (TO DO)
  1309.     
  1310.     return 0;
  1311. }
  1312.  
  1313. void        ZWindowManager::RestoreWindowPosition( ZWindow* aWindow, ZResourceFile* aFile, const short id )
  1314. {
  1315. #if _WPOS_WINDOW_PLACEMENT
  1316.  
  1317.     WPosHdl                wpH;
  1318.     ZResourceFile*        st;
  1319.     Rect                pr;
  1320.  
  1321.     FailNILParam( aWindow );
  1322.     
  1323.     // if <aFile> is NULL, use gPrefsFile if it exists. Otherwise do nothing.
  1324.     
  1325.     if ( aFile == NULL )
  1326.         st = (ZResourceFile*) gPrefsFile;
  1327.     else
  1328.         st = aFile;
  1329.         
  1330.     if ( st == NULL )
  1331.         return;
  1332.     
  1333.     // detach & read the pos resource, if any.
  1334.     
  1335.     short     rf = st->GetResourceRefNumber();
  1336.     
  1337.     try
  1338.     {
  1339.         st->OpenResFork();    
  1340.         wpH = (WPosHdl) st->ReadResource( kWindowPosResType, id );
  1341.         
  1342.         if ( wpH )
  1343.         {    
  1344.             // build the potential global rect of the window, to see if it's going to be on screen.
  1345.             // Note that under System 8.0+, the window frame can be dragged by its edges, but on
  1346.             // earlier systems only the title bar is draggable. We must check that a DRAGGABLE part of
  1347.             // the window is visible before moving it to that location.
  1348.             
  1349.             SetRect( &pr, 0, 0, (*wpH)->width, (*wpH)->height );
  1350.             OffsetRect( &pr, (*wpH)->globalH, (*wpH)->globalV );
  1351.             
  1352.             short    tBar = aWindow->GetTitleBarHeight();
  1353.             
  1354.             pr.top -= tBar;
  1355.             
  1356.             // modify rect according to titlebar height, and system, etc
  1357.             
  1358.             if ( gMacInfo.systemVersion < 0x0800 )
  1359.                 pr.bottom = pr.top + tBar;
  1360.             
  1361.             // if on screen, move the window. Otherwise leave it where it is:
  1362.             
  1363.             if ( WindowOnDesktop( &pr ))
  1364.                 aWindow->PlaceAt((*wpH)->globalH, (*wpH)->globalV );
  1365.         
  1366.             ReleaseResource((Handle) wpH );
  1367.         }
  1368.  
  1369.         if ( rf == _NOT_OPEN )
  1370.             st->CloseResFork();
  1371.     }
  1372.     catch( OSErr err )
  1373.     {
  1374.         if ( rf == _NOT_OPEN )
  1375.             st->CloseResFork();
  1376.             
  1377.         // don't propagate- it's not serious if this fails.
  1378.     }
  1379.     
  1380. #endif
  1381. }
  1382.  
  1383.  
  1384.  
  1385. #pragma mark -
  1386.  
  1387. /*---------------------------------***  BRINGBEHIND  ***--------------------------------*/
  1388. /*    
  1389. change the window ordering so it is behind another. If behindWindow is NULL, window is
  1390. brought to the front.
  1391. ----------------------------------------------------------------------------------------*/
  1392.  
  1393. void        ZWindowManager::BringBehind( ZWindow* aWindow, ZWindow* behindWindow )
  1394. {
  1395.     // brings <aWindow> behind <behindWindow>. If <behindWindow> is NULL, it is brought
  1396.     // to the front. This manipulates the mac windowlist to match the state here.
  1397.     
  1398.     WindowPtr    a, b;
  1399.     
  1400.     if ( behindWindow )
  1401.     {
  1402.         a = aWindow->GetMacWindow();
  1403.         b = behindWindow->GetMacWindow();
  1404.         
  1405.         SendBehind( a, b );
  1406.     }
  1407.     else
  1408.         BringToFront( aWindow->GetMacWindow()); 
  1409. }
  1410.  
  1411.  
  1412. /*-------------------------------***  POSTACTIVATION  ***-------------------------------*/
  1413. /*    
  1414. simulate an activation event for the window
  1415. ----------------------------------------------------------------------------------------*/
  1416.  
  1417. void        ZWindowManager::PostActivation( ZWindow* aWindow, Boolean state )    
  1418. {
  1419.     // posts an activate event for the window. This will be picked up by the event handler, which
  1420.     // will then maintain the command chain correctly. Floater activations are never sent in this
  1421.     // way, but their activate methods are called directly.
  1422.     
  1423.     if ( aWindow->IsVisible())
  1424.     {
  1425.         HiliteWindow( aWindow->GetMacWindow(), state );
  1426.     
  1427.         if ( aWindow->Floats())
  1428.         {
  1429.             if ( state )
  1430.                 aWindow->Activate();
  1431.             else
  1432.                 aWindow->Deactivate();
  1433.         }
  1434.         else
  1435.         {
  1436.             
  1437.             #if _ACTIVATE_EVENTS_ARE_REAL
  1438.             
  1439.             EvQElPtr    evQ;
  1440.             
  1441.             if ( aWindow )
  1442.             {
  1443.                 long        evtMessage = (long) aWindow->GetMacWindow();
  1444.                 
  1445.                 FailOSErr( PPostEvent( activateEvt, evtMessage, &evQ ));
  1446.                 
  1447.                 // set up the modifiers to indicate activation state
  1448.                 
  1449.                 if ( state )
  1450.                     evQ->evtQModifiers |= activeFlag;
  1451.                 else
  1452.                     evQ->evtQModifiers &= ~activeFlag;
  1453.             }
  1454.             
  1455.             #else
  1456.  
  1457.             ZEventHandler*    ze = gApplication->GetEventHandler();
  1458.             
  1459.             ze->HandleWindowActivate( aWindow->GetMacWindow(), state );
  1460.             
  1461.             #endif
  1462.         
  1463.             SendMessage( state? kWMMsgWindowActivated : kWMMsgWindowDeactivated, aWindow );
  1464.         }
  1465.     }
  1466. }
  1467.  
  1468.  
  1469. /*------------------------------***  CALCWINDOWRGNS  ***-------------------------------*/
  1470. /*    
  1471. calculate the union of the window structure regions in front of the window. This is used
  1472. to build a clip region for window dragging.
  1473. ----------------------------------------------------------------------------------------*/
  1474.  
  1475. void    ZWindowManager::CalcWindowRgns( ZWindow* aWindow, RgnHandle aRgn )
  1476. {
  1477.     // sets <theRgn> to the union of all windows in front if <aWindow>, including floaters.
  1478.     // This is used to form the clip region for a window drag. Note- this doesn't check the
  1479.     // parameters for sanity.
  1480.     
  1481.     SetEmptyRgn( aRgn );
  1482.     
  1483.     // the simplest way to achieve this is to scan the real mac window list, since that
  1484.     // allows us to treat the window ordering simply without consideration of our separate
  1485.     // lists.
  1486.     
  1487.     WindowPeek    w = (WindowPeek) FrontWindow();
  1488.     
  1489.     while (w && w != (WindowPeek) aWindow->GetMacWindow())
  1490.     {
  1491.         UnionRgn( w->strucRgn, aRgn, aRgn );
  1492.     
  1493.         w = w->nextWindow;
  1494.     }
  1495. }
  1496.  
  1497.  
  1498. /*------------------------------***  SHOWHIDEFLOATER  ***-------------------------------*/
  1499. /*    
  1500. show or hide a floater by moving it offscreen.
  1501. ----------------------------------------------------------------------------------------*/
  1502.  
  1503. void    ZWindowManager::ShowHideFloater( ZWindow* aFloater, Boolean hide )
  1504. {
  1505.     FailNILParam( aFloater );
  1506.     
  1507.     short        dh = 10000;
  1508.     Point        wLoc;
  1509.     WindowPtr    w = aFloater->GetMacWindow();
  1510.     Rect        dtBounds  = (*GetGrayRgn())->rgnBBox;
  1511.     
  1512.     if (! hide)
  1513.         dh = -dh;
  1514.         
  1515.     wLoc = topLeft( w->portRect );
  1516.     
  1517.     aFloater->Focus();
  1518.     LocalToGlobal( &wLoc );
  1519.     
  1520.     // don't attempt to hide or show more than once- it doesn't work. To this end we check
  1521.     // that the window is not already positioned
  1522.     
  1523.     if (( hide && wLoc.h < dtBounds.right ) ||
  1524.         ( ! hide && wLoc.h > dtBounds.right ))
  1525.         MoveWindow( w, wLoc.h + dh, wLoc.v, FALSE );    
  1526. }
  1527.  
  1528.  
  1529. /*-----------------------------***  BUILDWINDOWSMENU  ***-------------------------------*/
  1530. /*    
  1531. fill menu with current list of windows, and check current one.
  1532. ----------------------------------------------------------------------------------------*/
  1533.  
  1534. void    ZWindowManager::BuildWindowsMenu()
  1535. {
  1536.     short    n, i, mi;
  1537.     
  1538.     if ( wmMenu )
  1539.     {
  1540.         // delete items beyond initial number
  1541.         
  1542.         n = CountMenuItems( wmMenu );
  1543.         
  1544.         while( n > wmItemOffset )
  1545.             DeleteMenuItem( wmMenu, n-- );
  1546.             
  1547.         // set menu to window titles. If the offset was >0, add a dividing line first
  1548.         
  1549.         if ( wmWindows )
  1550.         {    
  1551.             ZWindow*    zw;
  1552.             Str255        title;
  1553.             
  1554.             n = wmWindows->CountItems();
  1555.             
  1556.             if (( wmItemOffset > 0 ) && ( n > 0 ))
  1557.                 AppendMenu( wmMenu, "\p-" );
  1558.         
  1559.             for( i = 1; i <= n; i++ )
  1560.             {
  1561.                 mi = i + wmItemOffset;
  1562.                 
  1563.                 if ( wmItemOffset > 0 )
  1564.                     mi++;    // allow for extra divider line
  1565.                 
  1566.                 zw = wmWindows->GetObject( i );
  1567.                 
  1568.                 zw->GetName( title );
  1569.                 
  1570.                 AppendMenu( wmMenu, "\px" );
  1571.                 SetMenuItemText( wmMenu, mi, title );
  1572.                 EnableItem( wmMenu, mi );
  1573.                 
  1574.                 // if window is active, check that item
  1575.                 
  1576.                 if ( zw == GetTopWindow())
  1577.                     CheckItem( wmMenu, mi, TRUE );
  1578.             }
  1579.         }
  1580.     }
  1581. }
  1582.  
  1583.  
  1584. Boolean        ZWindowManager::WindowOnDesktop( Rect* wFrame )
  1585. {
  1586.     // return TRUE if the rect passed intersects the desktop. Called by RestoreWindowPosition
  1587.     // to see if the restored position is legal on this system.
  1588.     
  1589.     RectRgn( gUtilRgn, wFrame );
  1590.     SectRgn( gUtilRgn, GetGrayRgn(), gUtilRgn );
  1591.  
  1592.     return ( ! EmptyRgn( gUtilRgn ));
  1593. }
  1594.  
  1595. #pragma mark -
  1596.  
  1597. // utils for establishing the global zoom source rect:
  1598.  
  1599. void    SetGlobalZoomSource( Rect* aGlobalRect )
  1600. {
  1601.     gZoomFXSourceRect = *aGlobalRect;
  1602. }
  1603.  
  1604.  
  1605. void    SetLocalZoomSource( Rect* aLocalRect )
  1606. {
  1607.     Rect    r = *aLocalRect;
  1608.     
  1609.     LocalToGlobal( &topLeft( r ));
  1610.     LocalToGlobal( &botRight( r ));
  1611.     
  1612.     SetGlobalZoomSource( &r );
  1613. }
  1614.  
  1615.